Crate static_toml

source ·
Expand description

Statically include TOML files.

This crate provides a simple way to statically embed data from TOML files at compile time. The provided macro static_toml! generates the necessary data types to represent the TOML data and assigns the parsed TOML data to a static variable.

Usage

Including a TOML file is simple. Here’s how to include some text messages defined in a toml:

# messages.toml

[info]
welcome = "Welcome to our application!"
update = "Your data has been updated successfully."

[errors]
file_not_found = "The requested file could not be found."
permission_denied = "You do not have permission to perform this action."
static_toml::static_toml! {
    static MESSAGES = include_toml!("messages.toml");
}

fn main() {
  // print the message from the toml file
  println!("{}", MESSAGES.info.welcome);
}

Accessing the values of nested data structures is done using the dot notation. IDEs capable of expanding proc macros (e.g. VS Code with rust-analyzer or CLion with the Rust plugin) should be able to provide code completion of the included TOML file. Using cargo doc on the crate this macro is called will also generate enough documentation to inspect the generated data types.

Syntax

The syntax is designed to be intuitive:

static_toml::static_toml! {
    [pub] static NAME_1 = include_toml!("file_1.toml");
    [pub] static NAME_2 = include_toml!("file_2.toml");
    ...
    [pub] static NAME_N = include_toml!("file_n.toml");
}

Note: Although this syntax looks like a typical static value assignment via include_*!, the data type is omitted. Instead, the data type is generated by the static_toml! macro call.

The include_toml! macro is part of the static_toml! macro and does not need to be imported separately.

In addition to pub, other visibilities may also be used. The passed visibility will automatically be applied to both the root module of the generated data types and the static value. For possible values, check Visibility and Privacy in The Rust Reference.

Attributes (including doc comments) are also supported:

static_toml::static_toml! {
    /// doc comments are supported
    #[allow(missing_docs)]
    #[derive(Debug)]
    static EXAMPLE = include_toml!("example.toml");
}

The macro attaches doc comments to the generated static value. Derive attributes are propagated through every constructed data type, allowing derive macros like Default to be used. Other attributes are attached to the root module containing the entry point of the generated data types.

Arrays

Arrays in TOML files can have different data types for each item. However, Rust’s slices require all elements to be of the same type. This crate aims to simplify access to TOML data, so it avoids using Option types to handle arrays.

The macro analyzes whether all items in an array have exactly the same data type. If this is the case, it will generate a fixed-sized slice of that data type, allowing you to iterate over the array and access elements using the [n] syntax.

If the items in the array do not all have the same data type, the macro will generate a tuple instead. This allows each position in the tuple to have a different data type. In cases where at least one item doesn’t match the data type structure of the others, a tuple will be generated. You can still index such a type easily, as tuples may be directly indexed via .n.

Configuration

You can configure the static_toml! macro call by applying a static_toml attribute to the items you want to configure.

  • #[static_toml(prefix = Prefix)]

    The macro will add the specified prefix to the beginning of each generated data type. The prefix should be a valid Rust identifier.


  • #[static_toml(suffix = Suffix)]

    The macro will add the specified suffix to the end of each generated data type.


  • #[static_toml(root_mod = toml)]

    Identifier of the root module that will contain the datatypes for the TOML file. If this is not set the name of the static value will be converted to snake_case and used a root mod name.


  • #[static_toml(values_ident = values)]

    When generating the value types for arrays, they need their own namespace. By default, this macro will use values for naming the modules and data types.


  • #[static_toml(prefer_slices = true)]

    This setting determines whether the macro should try to generate fixed size slices when working with arrays. If the setting is set to false, the macro will generate tuples for every array. By default, this is set to true.


  • #[static_toml(auto_doc = true)]

    By default, the macro generates documentation comments, including the file location and contents, enhancing visibility in the generated docs. Setting auto_doc to true ensures auto-generated documentation is appended after any existing manual comments. Conversely, setting it to false disables automatic documentation generation, which may result in the static item lacking documentation comments. This feature is particularly useful for easily accessing TOML contents within rustdoc.

You can combine attributes as follows:

static_toml::static_toml! {
    // all data types will be prefixed, suffixed and derive Default
    #[derive(Default)]
    #[static_toml(prefix = Prefix, suffix = Suffix)]
    static EXAMPLE = include_toml!("example.toml");
}

Using const

While the static_toml! macro is named for its primary functionality of statically including TOML files as static variables, it also supports the use of const variables. This option is provided to accommodate specific use cases where const is necessary.

The use of const can be crucial in scenarios such as const functions, which can refer to const variables but not to static variables, and const generics that require const values. When deciding between static and const, it’s important to consider the memory usage implications. The static keyword is ideal for large TOML files that should only occupy space in the application once, helping to optimize memory usage. In contrast, using const could potentially increase the binary size, especially if the same TOML data is reused multiple times. For further details on the static keyword in Rust, see the Rust documentation on static.

To use const within the static_toml! macro, simply replace static with const in the macro call. For example:

static_toml::static_toml! {
    const MESSAGES = include_toml!("messages.toml");
}

It’s also possible to mix static and const entries within the same static_toml! macro call. However, keep in mind that each identifier must be unique within the same scope. Here’s an example of using both static and const in a single macro call:

static_toml::static_toml! {
    static MESSAGES = include_toml!("messages.toml");
    const EXAMPLE = include_toml!("example.toml");
}

Implementation Details

For the specific details, check the documentation for static_toml!.

Macros